﻿using System;
using System.Text.RegularExpressions;
using System.Web;
using System.Reflection;
using Akabana.Amf.Messaging.Gateway.Configuration;
using Akabana.Amf.Messaging.Gateway.Service;
using Akabana.Amf.Messaging.Messages;
using Akabana.Amf.Util;
using log4net;

namespace Akabana.Amf.Messaging.Gateway
{
    public class MessagingGateway : IHttpModule
    {

        private static ILog logger = LogManager.GetLogger(typeof(MessagingGateway));

        private MessagingServiceProcessor remotingServiceProcessor;

        public void Dispose()
        {
            remotingServiceProcessor = null;
        }

        public virtual void Init(HttpApplication application)
        {
            lock (this)
            {

                remotingServiceProcessor = MessagingServiceProcessor.NewInstance();
                InitHttpApplicationEventHandlers(application);

                TypeResolver.AddType("flex.messaging.messages.AcknowledgeMessage", typeof(AcknowledgeMessage));
                TypeResolver.AddType("flex.messaging.messages.CommandMessage", typeof(CommandMessage));
                TypeResolver.AddType("flex.messaging.messages.RemotingMessage", typeof(RemotingMessage));
                TypeResolver.AddType("DSK", typeof(AcknowledgeMessageExt));

                var ass = Assembly.GetExecutingAssembly();

                AssemblyLoader.RegisterAssembly(ass);
            }
        }

        private void InitHttpApplicationEventHandlers(HttpApplication application)
        {
#if DEBUG
            application.AcquireRequestState += (sender, eventArgs) => { logger.Debug("AcquireRequestState"); };
            application.AuthenticateRequest += (sender, eventArgs) => { logger.Debug("AuthenticateRequest"); };
            application.AuthorizeRequest += (sender, eventArgs) => { logger.Debug("AuthorizeRequest"); };
            application.BeginRequest += (sender, eventArgs) => { logger.Debug("BeginRequest"); };
            application.Disposed += (sender, eventArgs) => { logger.Debug("Disposed"); };
            application.EndRequest += (sender, eventArgs) => { logger.Debug("EndRequest"); };
            application.Error += (sender, eventArgs) => { logger.Debug("Error"); };
            //application.LogRequest += (sender, eventArgs) => { logger.Debug("LogRequest"); };
            //application.MapRequestHandler += (sender, eventArgs) => { logger.Debug("MapRequestHandler"); };
            application.PostAcquireRequestState += (sender, eventArgs) => { logger.Debug("PostAcquireRequestState"); };
            application.PostAuthenticateRequest += (sender, eventArgs) => { logger.Debug("PostAuthenticateRequest"); };
            application.PostAuthorizeRequest += (sender, eventArgs) => { logger.Debug("PostAuthorizeRequest"); };
            //application.PostLogRequest += (sender, eventArgs) => { logger.Debug("PostLogRequest"); };
            //application.PostMapRequestHandler += (sender, eventArgs) => { logger.Debug("PostMapRequestHandler"); };
            application.PostReleaseRequestState += (sender, eventArgs) => { logger.Debug("PostReleaseRequestState"); };
            application.PostRequestHandlerExecute += (sender, eventArgs) => { logger.Debug("PostRequestHandlerExecute"); };
            application.PostResolveRequestCache += (sender, eventArgs) => { logger.Debug("PostResolveRequestCache"); };
            application.PostUpdateRequestCache += (sender, eventArgs) => { logger.Debug("PostUpdateRequestCache"); };
            application.PreRequestHandlerExecute += (sender, eventArgs) => { logger.Debug("PreRequestHandlerExecute"); };
            application.PreSendRequestContent += (sender, eventArgs) => { logger.Debug("PreSendRequestContent"); };
            application.PreSendRequestHeaders += (sender, eventArgs) => { logger.Debug("PreSendRequestHeaders"); };
            application.ReleaseRequestState += (sender, eventArgs) => { logger.Debug("ReleaseRequestState"); };
            application.ResolveRequestCache += (sender, eventArgs) => { logger.Debug("ResolveRequestCache"); };
            application.UpdateRequestCache += (sender, eventArgs) => { logger.Debug("UpdateRequestCache"); };
#endif

            application.PreRequestHandlerExecute += new EventHandler(ApplicationPreRequestHandlerExecuteHandler);
            application.EndRequest += new EventHandler(ApplicationEndRequestHandler);
            application.Error += new EventHandler(ApplicationErrorHandler);
        }

        private void ApplicationPreRequestHandlerExecuteHandler(object sender, EventArgs eventArgs)
        {
            var app = (HttpApplication)sender;
            var Request = app.Request;
            var Response = app.Response;

            if (Request.IsPostMethod())
            {
                if (Regex.IsMatch(Request.Path, MessagingGatewayConfiguration.Settings.EndPoint))
                {
                    remotingServiceProcessor.Process(Request, Response);
                    app.CompleteRequest();
                }
#if DEBUG
                else
                {
                    logger.Debug("other access:" + Request.Url);
                }
#endif
            }
        }

        private void ApplicationEndRequestHandler(object sender, EventArgs e)
        {
#if DEBUG
            var app = (HttpApplication)sender;
            logger.DebugFormat("RequestEnd @app:{0},err:{1}", app, e);
#endif
        }

        private void ApplicationErrorHandler(object sender, EventArgs e)
        {
#if DEBUG
            var app = (HttpApplication)sender;
            logger.ErrorFormat("Error @app:{0},err:{1}", app, e);
#endif
        }
    }
}
